/*
 * Copyright (c) 2006-2019, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author          Notes
 * 2019-08-15     xiangxistu      the first version
 */

#ifndef __PPP_DEVICE_H__
#define __PPP_DEVICE_H__
#include <Arduino.h>
#include<HardwareSerial.h>
#include<core_debug.h>
#include <netif/ppp/ppp.h>
#include <netif/ppp/pppos.h>
#include <netif/ppp/pppapi.h>
#include <lwip/dns.h>
#include <lwip/netif.h>

typedef unsigned int u32;
typedef unsigned short u16;
typedef unsigned char u8;

#ifndef PPP_DEVICE_NAME
#define PPP_DEVICE_NAME "pp"
#endif
#define PPP_PRIVATE_APN ""
#define PPP_DAIL_CMD "ATD*99#" /* common dailing cmd */
#ifndef PPP_USING_PUBLIC_APN
#define PPP_APN_CMD "AT+CGDCONT=1,\"IP\"," PPP_PRIVATE_APN
#else
#ifdef PPP_APN_CMCC
#define PPP_APN_CMD "AT+CGDCONT=1,\"IP\",\"CMNET\"" /* China Mobile Communication Company */
#endif
#ifdef PPP_APN_CUCC
#define PPP_APN_CMD "AT+CGDCONT=1,\"IP\",\"UNINET\"" /* China Unicom Communication Company */
#endif
#ifdef PPP_APN_CTCC
#define PPP_APN_CMD "AT+CGDCONT=1,\"IP\",\"CTNET\"" /* China Telecom Communication Company */
#endif
#endif
#define PPP_CTL_GET_CSQ 1
#define PPP_CTL_GET_IEMI 2
#define PPP_CTL_GET_TYPE 3
#define PPP_CTL_PREPARE 10

#define PPP_FRAME_MAX 1550
#define PPP_DROP_BUF PPP_FRAME_MAX

#define PPP_DEVICE_SW_VERSION "1.1.1"
#define PPP_DEVICE_SW_VERSION_NUM 0x10101

enum ppp_trans_type
{
    PPP_TRANS_CHAT,
    PPP_TRANS_AT_CLIENT
};

enum ppp_conn_type
{
    PPP_CONNET_UART, /* using uart connect ppp */
    PPP_CONNET_USB   /* using  usb connect ppp */
};

/**
 * @brief PPPoS Client IP Information
 *
 */
struct ppp_device
{
    int parent;          /* join rt_device frame */
    HardwareSerial * uart;                 /* low-level uart device object */
    const struct ppp_device_ops *ops; /* ppp device ops interface */
    enum ppp_conn_type conn_type;     /* using usb or uart */
    u32 power_pin;              /* power pin, if device need hardware reset */

    ppp_pcb *pcb; /* ppp protocol control block */
    struct netif pppif;

#ifdef PPP_DEVICE_DEBUG_DROP
    u32 dropcnt;              /* counter of drop bytes */
    u32 droppos;              /* valid size of drop buffer */
    u8 dropbuf[PPP_DROP_BUF]; /* drop buffer */
#endif

    u32 rxpos;               /* valid size of receive frame buffer */
    u8 rxbuf[PPP_FRAME_MAX]; /* receive frame buffer */
    u8 state;                /* internal state */

    int event; /* interthread communication */

    int recv_tid; /* recieve thread point */
    void *user_data;      /* reserve */
};

struct ppp_device_ops
{
    int (*prepare)(struct ppp_device *dev);
};

enum ppp_reci_status
{
    PPP_DATA_VERIFY,
    PPP_DATA_START,
    PPP_DATA_END
};

/* store at_client rx_callback function */
typedef int (*uart_rx_cb)(HardwareSerial *dev, u32 size);

/* offer register funciton to user */
int ppp_device_register(struct ppp_device *ppp_device, const char *dev_name, const char *uart_name, void *user_data);
int ppp_device_attach(struct ppp_device *ppp_device, const char *uart_name, void *user_data);
int ppp_device_detach(struct ppp_device *ppp_device);

#endif /* __PPP_DEVICE_H__ */
